package woaini.fenger.core.bot.base.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpUtil;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
import woaini.fenger.core.bot.base.Bot;
import woaini.fenger.core.bot.base.IBotAdapter;
import woaini.fenger.core.bot.communication.base.BaseBotRequest;
import woaini.fenger.core.bot.config.WsClientBotConfig;
import woaini.fenger.core.bot.enums.ConnectType;
import woaini.fenger.core.bot.event.BaseEvent;
import woaini.fenger.core.utils.ThreadTool;

/**
 * WS客户端机器人 封装了 自动重连什么的
 *
 * @see WsClientBot
 * @author yefeng {@code @Date} 2023-05-16 16:50:39
 */
@Slf4j
public class WsClientBot extends Bot {

  private final WsClientBotConfig botConfig;
  private WebSocketClient webSocketClient;

  public WsClientBot(WsClientBotConfig botConfig) {
    super(botConfig);
    this.botConfig = botConfig;
    init();
  }

  public void init() {
    // 进行初始化客户端操作
    // 判断是否存在参数进行参数拼接
    String url = botConfig.getEndpoint();
    Map<String, Object> params = botConfig.getParams();
    Map<String, String> headers = botConfig.getHeaders();
    if (MapUtil.isNotEmpty(params)) {
      url = HttpUtil.urlWithForm(url, params, StandardCharsets.UTF_8, false);
    }

    URI uri = null;
    try {
      uri = new URI(url);
    } catch (Exception e) {
    }
    if (uri == null) {
      log.error("socketClient创建uri失败:{}", uri);
      return;
    }
    if (MapUtil.isNotEmpty(headers)) {
      webSocketClient =
          new BotWebSocketClient(uri, new Draft_6455(), headers, this, botConfig, url);
    } else {
      webSocketClient = new BotWebSocketClient(uri, new Draft_6455(), this, botConfig, url);
    }
  }

  @Override
  public void conncet() {
    webSocketClient.connect();
  }

  @Override
  public void reConncet() {
    webSocketClient.reconnect();
  }

  @Override
  public void send(BaseBotRequest messages) {
      this.webSocketClient.send(JSONObject.toJSONString(messages));
  }

  public static class BotWebSocketClient extends WebSocketClient {

    private final Bot bot;

    private final WsClientBotConfig botConfig;

    private final String finalUrl;

    public BotWebSocketClient(
        URI serverUri, Draft protocolDraft, Bot bot, WsClientBotConfig botConfig, String finalUrl) {
      super(serverUri, protocolDraft);
      this.bot = bot;
      this.botConfig = botConfig;
      this.botConfig.setReceiveType(ConnectType.WS_CLIENT);
      this.finalUrl = finalUrl;
    }

    public BotWebSocketClient(
        URI serverUri,
        Draft protocolDraft,
        Map<String, String> httpHeaders,
        Bot bot,
        WsClientBotConfig botConfig,
        String finalUrl) {
      super(serverUri, protocolDraft, httpHeaders);
      this.bot = bot;
      this.botConfig = botConfig;
      this.finalUrl = finalUrl;
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {
      log.info("socket链接成功:{},{}", botConfig.getSelfId(), finalUrl);
      bot.online();
    }

    @Override
    public void onMessage(String s) {
      log.info("socket消息:{},{}", botConfig.getSelfId(), s);
      //解析原始数据
      BaseEvent message = this.bot.getBotAdapter().decode(this.botConfig.getReceiveType(),s);
      if (message == null){
        return;
      }
      //此处进行异步处理
      ThreadTool.run(() -> {
        this.bot.receive(message);
      });
    }

    @Override
    public void onClose(int i, String s, boolean b) {
      log.info("socket关闭:{},{}", botConfig.getSelfId(), finalUrl);
      bot.offline();
    }

    @Override
    public void onError(Exception e) {
      log.error("socket异常:{},{}", botConfig.getSelfId(), finalUrl, e);
    }
  }
}
